package basicutil.common;

import com.sun.javafx.scene.traversal.Direction;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

public final class Point implements Comparable<Point> {
    private static final Point[][] instances = new Point[20][20];

    static {
        for (int i = 0; i < instances.length; i++) {
            for (int j = 0; j < instances[i].length; j++) {
                instances[i][j] = new Point(i, j);
            }
        }
    }

    public final int row, col;

    public static boolean within(Point p, int rowBound, int colBound) {
        return p.row >= 0 && p.row < rowBound && p.col >= 0 && p.col < colBound;
    }

    // 返回两个同一行或同一列的点之间的所有点，不包括本身，不过不同行不同列返回空
    // 从小到大排列
    public static List<Point> between(Point start, Point end) {
        List<Point> re = new ArrayList<>();
        if (start.row == end.row) {

            for (int i = start.col + 1; i < end.col; i++) {
                re.add(Point.of(start.row, i));
            }

            for (int i = end.col + 1; i < start.col; i++) {
                re.add(Point.of(start.row, i));
            }
        }
        if (start.col == end.col) {

            for (int i = start.row + 1; i < end.row; i++) {
                re.add(Point.of(i, start.col));
            }

            for (int i = end.row + 1; i < start.row; i++) {
                re.add(Point.of(i, start.col));
            }
        }
        return re;
    }

    public static Point of(int rowIndex, int colIndex) {
        if (rowIndex >= 0 && rowIndex < instances.length && colIndex >= 0 && colIndex < instances[0].length) {
            return instances[rowIndex][colIndex];
        }
        return new Point(rowIndex, colIndex);
    }

    private Point(int rowIndex, int colIndex) {
        this.row = rowIndex;
        this.col = colIndex;
    }

    public Point add(Point other) {
        return Point.of(row + other.row, col + other.col);
    }

    public Point up() {
        return Point.of(row - 1, col);
    }

    public Point left() {
        return Point.of(row, col - 1);
    }

    public Point down() {
        return Point.of(row + 1, col);
    }

    public Point right() {
        return Point.of(row, col + 1);
    }

    public Direction getDirection(Point another) {
        if (this.row == another.row) {
            if (this.col < another.col) {
                return Direction.RIGHT;
            } else {
                return Direction.LEFT;
            }
        } else if (this.col == another.col) {
            if (this.row < another.row) {
                return Direction.DOWN;
            } else {
                return Direction.UP;
            }
        }
        return null;
    }

    public int getRow() {
        return row;
    }

    public int getCol() {
        return col;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Point point = (Point) o;
        return row == point.row && col == point.col;
    }

    @Override
    public int hashCode() {
        return Objects.hash(row, col);
    }

    @Override
    public String toString() {
        return "Point{" + "row=" + row + ", col=" + col + '}';
    }

    public String toMousePosString() {
        return col + ", " + row;
    }

    @Override
    public int compareTo(Point o) {

        return Integer.compare(this.row * 10000 + this.col, o.row * 10000 + o.col);
    }
}
